﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using SharpGL;
//using System.Windows.Forms;
//using System.Drawing;
//using System.Diagnostics;

//namespace bitzhuwei.SharpGLController
//{
//    public class ViewController
//    {
//        public event EventHandler<CameraEventArgs> CameraChanged;

//        public override string ToString()
//        {
//            return string.Format("eye:{0},center:{1},up:{2},perspective:[{3}]", eye, center, up, perspective);
//            //return base.ToString();
//        }
//        private TriTuple eye;
//        private TriTuple center;
//        private TriTuple up;
//        private SharpGL.OpenGLControl graphics;
//        private PerspectiveParam perspective;
//        private bool isStarted;

//        public ViewController(SharpGL.OpenGLControl graphics, double aspect)
//            : this(graphics, -5, 5, -5, 0, 0, 0, 0, 1, 0, 60.0f, aspect, 0.01, 100.0)
//        {
//            this.Init(graphics, -5, 5, -5, 0, 0, 0, 0, 1, 0, 60.0f, aspect, 0.01, 100.0);
//        }
//        public ViewController(SharpGL.OpenGLControl graphics, double eyex, double eyey, double eyez,
//            double centerx, double centery, double centerz,
//            double upx, double upy, double upz, double fovy, double aspect, double zNear, double zFar)
//        {
//            this.Init(graphics, eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz, fovy, aspect, zNear, zFar);
//        }

//        public ViewController(OpenGLControl openGLControl)
//        {
//            // TODO: Complete member initialization
//            Debug.Assert(openGLControl != null);
//            this.Init(openGLControl, -5, 5, -5, 0, 0, 0, 0, 1, 0, 60.0f,
//                (double)(openGLControl.Width) / (double)(openGLControl.Height), 0.01, 100.0);
//        }

//        private void Init(SharpGL.OpenGLControl graphics, double eyex, double eyey, double eyez,
//            double centerx, double centery, double centerz,
//            double upx, double upy, double upz, double fovy, double aspect, double zNear, double zFar)
//        {
//            this.graphics = graphics;
//            this.eye = new TriTuple(eyex, eyey, eyez);
//            this.center = new TriTuple(centerx, centery, centerz);
//            this.up = new TriTuple(upx, upy, upz);
//            this.perspective = new PerspectiveParam(fovy, aspect, zNear, zFar);
//        }

//        public bool IsStarted()
//        {
//            return this.isStarted;
//        }

//        System.Windows.Forms.KeyEventHandler keyDownEvent;
//        System.Windows.Forms.KeyEventHandler keyUpEvent;
//        System.Windows.Forms.MouseEventHandler mouseDownEvent;
//        System.Windows.Forms.MouseEventHandler mouseMoveEvent;
//        System.EventHandler mouseEnterEvent;
//        System.EventHandler mouseLeaveEvent;
//        System.EventHandler resizedEvent;
//        public void Start()
//        {
//            if (!this.isStarted && this.graphics != null && !this.graphics.IsDisposed)
//            {
//                if (keyDownEvent == null)
//                    keyDownEvent = new System.Windows.Forms.KeyEventHandler(graphics_KeyDown);
//                this.graphics.KeyDown += keyDownEvent;
//                if (keyUpEvent == null)
//                    keyUpEvent = new System.Windows.Forms.KeyEventHandler(graphics_KeyUp);
//                this.graphics.KeyUp += keyUpEvent;
//                if (mouseDownEvent == null)
//                    mouseDownEvent = new MouseEventHandler(graphics_MouseDown);
//                this.graphics.MouseDown += mouseDownEvent;
//                if (mouseMoveEvent == null)
//                    mouseMoveEvent = new MouseEventHandler(graphics_MouseMove);
//                this.graphics.MouseMove += mouseMoveEvent;
//                if (mouseEnterEvent == null)
//                    mouseEnterEvent = new EventHandler(graphics_MouseEnter);
//                this.graphics.MouseEnter += mouseEnterEvent;
//                if (mouseLeaveEvent == null)
//                    mouseLeaveEvent = new EventHandler(graphics_MouseLeave);
//                this.graphics.MouseLeave += mouseLeaveEvent;
//                if (resizedEvent == null)
//                    resizedEvent = new EventHandler(graphics_Resized);
//                this.graphics.Resized += resizedEvent;
//                this.isStarted = true;
//                this.graphics_Resized(graphics, null);
//            }
//        }

//        void graphics_MouseLeave(object sender, EventArgs e)
//        {
//            //throw new NotImplementedException();
//        }

//        void graphics_MouseEnter(object sender, EventArgs e)
//        {
//            this.currentLocation = Control.MousePosition;
//            var item = this.graphics.Parent;
//            Control preItem = this.graphics;
//            while (item != null)
//            {
//                preItem = item;
//                item = item.Parent;
//            }
//            this.currentLocation.Offset(preItem.Location);
//        }

//        void graphics_Resized(object sender, EventArgs e)
//        {
//            this.UpdateView();
//        }

//        private double _turnAngle = 0.005;

//        /// <summary>
//        /// Turn left/right
//        /// </summary>
//        public double TurnAngle
//        {
//            get { return _turnAngle; }
//            set { _turnAngle = value; }
//        }

//        private double _staggerAngle = 0.005;

//        /// <summary>
//        /// Stagger angle
//        /// </summary>
//        public double StaggerAngle
//        {
//            get { return _staggerAngle; }
//            set { _staggerAngle = value; }
//        }

//        void graphics_MouseMove(object sender, MouseEventArgs e)
//        {
//            if (e.Button == System.Windows.Forms.MouseButtons.Left)
//            {
//                var angle = (e.Location.X - currentLocation.X) * TurnAngle;
//                currentLocation = e.Location;
//                Turn(angle);
//                UpdateView();
//            }
//        }

//        Point currentLocation = Point.Empty;

//        void graphics_MouseDown(object sender, MouseEventArgs e)
//        {
//            currentLocation = e.Location;
//        }

//        private double _step = 0.2;

//        /// <summary>
//        /// Step front/back, left/right. Or go up/down
//        /// </summary>
//        public double Step
//        {
//            get { return _step; }
//            set { _step = value; }
//        }

//        Direction _keyDownDirection;//= Direction.None;

//        void graphics_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
//        {
//            if ((e.KeyCode) == Keys.W
//                || (e.KeyCode) == Keys.Up)
//            {
//                _keyDownDirection |= Direction.Front;
//            }
//            if ((e.KeyCode) == Keys.S
//                || (e.KeyCode) == Keys.Down)
//            {
//                _keyDownDirection |= Direction.Back;
//            }
//            if ((e.KeyCode) == Keys.A
//                || (e.KeyCode) == Keys.Left)
//            {
//                _keyDownDirection |= Direction.Left;
//            }
//            if ((e.KeyCode) == Keys.D
//                || (e.KeyCode) == Keys.Right)
//            {
//                _keyDownDirection |= Direction.Right;
//            }
//            if ((e.KeyCode) == Keys.Q
//                || (e.KeyCode == Keys.PageUp))
//            {
//                _keyDownDirection |= Direction.Up;
//            }
//            if ((e.KeyCode) == Keys.E
//                || (e.KeyCode == Keys.PageDown))
//            {
//                _keyDownDirection |= Direction.Down;
//            }

//            var moving = false;
//            {
//                var frontBack = _keyDownDirection & (Direction.Front | Direction.Back);
//                if (frontBack != (Direction.Front | Direction.Back))
//                {
//                    moving = true;
//                    if (frontBack == Direction.Front)
//                        this.GoFront(Step);
//                    else if (frontBack == Direction.Back)
//                        this.GoBack(Step);
//                }
//            }
//            {
//                var leftRight = _keyDownDirection & (Direction.Left | Direction.Right);
//                if (leftRight != (Direction.Left | Direction.Right))
//                {
//                    moving = true;
//                    if (leftRight == Direction.Left)
//                        this.GoLeft(Step);
//                    else if (leftRight == Direction.Right)
//                        this.GoRight(Step);
//                }
//            }
//            {
//                var upDown = _keyDownDirection & (Direction.Up | Direction.Down);
//                if (upDown != (Direction.Up | Direction.Down))
//                {
//                    moving = true;
//                    if (upDown == Direction.Up)
//                        this.GoUp(Step);
//                    else if (upDown == Direction.Down)
//                        this.GoDown(Step);
//                }
//            }

//            if (moving)
//                this.UpdateView();
//        }

//        void graphics_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
//        {
//            if ((e.KeyCode) == Keys.W
//                || (e.KeyCode) == Keys.Up)
//            {
//                _keyDownDirection &= ~Direction.Front;
//            }
//            if ((e.KeyCode) == Keys.S
//                || (e.KeyCode) == Keys.Down)
//            {
//                _keyDownDirection &= ~Direction.Back;
//            }
//            if ((e.KeyCode) == Keys.A
//                || (e.KeyCode) == Keys.Left)
//            {
//                _keyDownDirection &= ~Direction.Left;
//            }
//            if ((e.KeyCode) == Keys.D
//                || (e.KeyCode) == Keys.Right)
//            {
//                _keyDownDirection &= ~Direction.Right;
//            }
//            if ((e.KeyCode) == Keys.Q
//                || (e.KeyCode == Keys.PageUp))
//            {
//                _keyDownDirection &= ~Direction.Up;
//            }
//            if ((e.KeyCode) == Keys.E
//                || (e.KeyCode == Keys.PageDown))
//            {
//                _keyDownDirection &= ~Direction.Down;
//            }
//        }

//        public void Stop()
//        {
//            if (this.isStarted)
//            {
//                if (this.graphics == null || this.graphics.IsDisposed)
//                {
//                    this.isStarted = false;
//                }
//                else
//                {
//                    if (keyDownEvent != null)
//                        this.graphics.KeyDown -= keyDownEvent;
//                    if (keyUpEvent != null)
//                        this.graphics.KeyUp -= keyUpEvent;
//                    if (mouseDownEvent != null)
//                        this.graphics.MouseDown -= mouseDownEvent;
//                    if (mouseMoveEvent != null)
//                        this.graphics.MouseMove -= mouseMoveEvent;
//                    if (mouseEnterEvent != null)
//                        this.graphics.MouseEnter -= mouseEnterEvent;
//                    if (mouseLeaveEvent != null)
//                        this.graphics.MouseLeave -= mouseLeaveEvent;
//                    if (resizedEvent != null)
//                        this.graphics.Resized -= resizedEvent;
//                    this.isStarted = false;
//                }
//            }
//        }

//        public void GoFront(double step)
//        {
//            if (graphics == null) return;

//            var diff = new TriTuple(this.center.X - this.eye.X,
//                0,
//                this.center.Z - this.eye.Z);
//            var length2 = diff.X * diff.X + 0 + diff.Z * diff.Z;
//            var radio = Math.Sqrt(step * step / length2);
//            var stepDiff = new TriTuple(diff.X * radio, 0, diff.Z * radio);

//            this.eye.Add(stepDiff);
//            this.center.Add(stepDiff);
//        }

//        public void GoBack(double step)
//        {
//            if (graphics == null) return;

//            var diff = new TriTuple(this.center.X - this.eye.X,
//                0,
//                this.center.Z - this.eye.Z);
//            var length2 = diff.X * diff.X + 0 + diff.Z * diff.Z;
//            var radio = Math.Sqrt(step * step / length2);
//            var stepDiff = new TriTuple(-diff.X * radio, 0, -diff.Z * radio);

//            this.eye.Add(stepDiff);
//            this.center.Add(stepDiff);
//        }

//        public void GoLeft(double step)
//        {
//            if (graphics == null) return;

//            var diff = new TriTuple(this.center.X - this.eye.X,
//                0,
//                this.center.Z - this.eye.Z);
//            var length2 = diff.X * diff.X + 0 + diff.Z * diff.Z;
//            var radio = Math.Sqrt(step * step / length2);
//            var stepDiff = new TriTuple(diff.Z * radio, 0, -diff.X * radio);

//            this.eye.Add(stepDiff);
//            this.center.Add(stepDiff);
//        }

//        public void GoRight(double step)
//        {
//            if (graphics == null) return;

//            var diff = new TriTuple(this.center.X - this.eye.X,
//                0,
//                this.center.Z - this.eye.Z);
//            var length2 = diff.X * diff.X + 0 + diff.Z * diff.Z;
//            var radio = Math.Sqrt(step * step / length2);
//            var stepDiff = new TriTuple(-diff.Z * radio, 0, diff.X * radio);

//            this.eye.Add(stepDiff);
//            this.center.Add(stepDiff);
//        }

//        public void GoUp(double step)
//        {
//            if (graphics == null) return;

//            this.eye.Y = this.eye.Y + step;
//            this.center.Y = this.center.Y + step;
//        }

//        public void GoDown(double step)
//        {
//            if (graphics == null) return;

//            this.eye.Y = this.eye.Y - step;
//            this.center.Y = this.center.Y - step;
//        }

//        /// <summary>
//        /// 正数向右转，负数向左转
//        /// </summary>
//        /// <param name="angle"></param>
//        public void Turn(double angle)
//        {
//            if (graphics == null) return;

//            var diff = new TriTuple(this.center.X - this.eye.X,
//                0,
//                this.center.Z - this.eye.Z);
//            var cos = Math.Cos(angle);
//            var sin = Math.Sin(angle);
//            var centerDiff = new TriTuple(diff.X * cos - diff.Z * sin,
//                0,
//                diff.X * sin + diff.Z * cos);
//            this.center.X = this.eye.X + centerDiff.X;
//            this.center.Z = this.eye.Z + centerDiff.Z;
//        }


//        public void UpdateView()
//        {
//            if (graphics == null) return;

//            var gl = graphics.OpenGL;
//            gl.MatrixMode(OpenGL.GL_PROJECTION);
//            gl.LoadIdentity();
//            var perspective = this.perspective;
//            //  Create a perspective transformation.
//            gl.Perspective(perspective.fovy, perspective.aspect, perspective.zNear, perspective.zFar);
//            //  Use the 'look at' helper function to position and aim the camera.
//            var eye = this.eye; var center = this.center; var up = this.up;
//            gl.LookAt(eye.X, eye.Y, eye.Z,
//                center.X, center.Y, center.Z,
//                up.X, up.Y, up.Z);
//            gl.MatrixMode(OpenGL.GL_MODELVIEW);
//            if (this.CameraChanged != null)
//            {
//                this.CameraChanged(this, new CameraEventArgs(eye, center, up, perspective));
//            }
//        }

//        public Direction GetDirection()
//        {
//            return this._keyDownDirection;
//        }
//    }

//}
